home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Napster Protocol
- */
-
- #include "include/config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <proto/exec.h>
- #include <proto/socket.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <netinet/tcp.h>
- #include <bsdsocket/socketbasetags.h>
- #include <error.h>
-
- #include "include/gui.h"
- #include "include/channellist.h"
- #include "include/hotlist.h"
- #include "include/msg.h"
- #include "include/napster.h"
- #include "include/navigator.h"
- #include "include/protos.h"
- #include "include/prefs.h"
- #include "include/share.h"
- #include "include/transfer.h"
- #include "include/download.h"
- #include "include/upload.h"
- #include "amster_Cat.h"
-
- #define NAP_SWAPIP(x) ( ((x&0xFF)<<24) | ((x&0xFF00)<<8) | ((x&0xFF0000)>>8) | (x>>24) )
-
- struct Library *SocketBase=NULL;
- u_long nap_sigmask;
- long nap_sock= -1;
- long loc_sock= -1;
-
- char nap_host[512];
- char nap_server[512+6];
-
- int nap_state= -1;
- #define NAPS_OFF -1
- #define NAPS_MAINCON 0
- #define NAPS_MAINON 1
- #define NAPS_CON 2
- #define NAPS_ON 3
-
- char nap_buffer[AMSTER_NAPBUFSIZE];
- char *nap_buf = &nap_buffer[4];
-
- char *nap_linktype[] = {
- (char*)_MSG_LINE_UNKNOWN,
- (char*)_MSG_LINE_14400,
- (char*)_MSG_LINE_28800,
- (char*)_MSG_LINE_33600,
- (char*)_MSG_LINE_57600,
- (char*)_MSG_LINE_64000,
- (char*)_MSG_LINE_128000,
- (char*)_MSG_LINE_CABLE,
- (char*)_MSG_LINE_DSL,
- (char*)_MSG_LINE_T1,
- (char*)_MSG_LINE_T3,
- NULL
- };
-
- BOOL nap_logininit(void);
- int nap_connect(char *server);
- int nap_recv(u_char *buf);
- void nap_interpret(u_int com, char *data);
- void nap_parseresult(int type, char *data);
- char *nap_token(char **s);
- u_long nap_ltoken(char **str);
- int nap_itoken(char **str);
- int createlistener(void);
- char *getneterror(int type);
-
-
- void nap_login_fromlist(char *server)
- {
- if (!nap_logininit()) return;
-
- nap_state = NAPS_CON;
- gui_stat((char*)MSG_STATUS2_CONNECTINGTO, server);
- if (!nap_connect(server)) {
- nap_logout();
- return;
- }
- }
-
-
- void nap_login(void)
- {
- if (!nap_logininit()) return;
-
- if (prf->server) {
- nap_state = NAPS_CON;
- gui_stat((char*)MSG_STATUS2_CONNECTINGTO, prf->server);
- if (!nap_connect(prf->server)) {
- nap_logout();
- return;
- }
- }
- else {
- nap_state = NAPS_MAINCON;
- gui_stat((char*)MSG_STATUS2_FINDINGOPTIMAL);
- if (!nap_connect(prf->mainserver)) {
- nap_logout();
- return;
- }
- }
- }
-
-
- BOOL nap_logininit(void)
- {
- gui_state(0);
- SocketBase = OpenLibrary("bsdsocket.library", 0);
- if (!SocketBase) {
- gui_stat((char *)MSG_NO_TCPIP);
- nap_logout();
- return FALSE;
- }
- SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK), (char *)nap_sigmask, TAG_DONE);
-
- return TRUE;
- }
-
-
- void nap_logout(void)
- {
- nap_state = NAPS_OFF;
- if (nap_sock>=0) CloseSocket(nap_sock);
- nap_sock = -1;
- if (loc_sock>=0) CloseSocket(loc_sock);
- loc_sock = -1;
- if (SocketBase) CloseLibrary(SocketBase);
- SocketBase = NULL;
- gui_state(-1);
- }
-
-
- void nap_listen(void)
- {
- static u_char buf[AMSTER_NAPBUFSIZE];
- static struct fd_set fds;
- static struct timeval tv;
-
- if (nap_state == NAPS_OFF) return;
-
- FD_ZERO(&fds);
- FD_SET(nap_sock,&fds);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- switch (nap_state) {
- case NAPS_MAINCON:
- if (WaitSelect(nap_sock+1,NULL,&fds,NULL,&tv,0) != 1) break;
- {
- long tmp=0;
- IoctlSocket(nap_sock,FIONBIO,(char*)&tmp);
- nap_state = NAPS_MAINON;
- }
-
- case NAPS_MAINON:
- if (WaitSelect(nap_sock+1,&fds,NULL,NULL,&tv,0) != 1) break;
- {
- int r;
- char *col;
- r = recv(nap_sock, buf, 255,0);
- CloseSocket(nap_sock);
- nap_sock = -1;
- if (r <= 0) {
- gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_server, getneterror(Errno()));
- nap_logout();
- return;
- }
- buf[r] = 0;
- col = strchr(buf, '\n');
- if (col) *col=0;
- if (strncmp(buf,"wait",4)==0 || strncmp(buf,"busy",4)==0 || strncmp(buf,"127.0.0.1",9)==0) {
- /* Sometimes the server returns "127.0.0.1:1111" - quite odd. */
- gui_stat((char *)MSG_INFO_SERVERBUSY);
- nap_logout();
- return;
- }
- gui_debugf((char *)MSG_INFO_OPTIMAL, buf);
- gui_stat((char *)MSG_STATUS2_CONNECTINGTO, buf);
- if (!nap_connect(buf)) {
- nap_logout();
- return;
- }
- nap_state = NAPS_CON;
- }
- break;
-
- case NAPS_CON:
- if (WaitSelect(nap_sock+1,NULL,&fds,NULL,&tv,0) != 1) break;
- {
- long tmp=0;
- int r = 0;
-
- IoctlSocket(nap_sock, FIONBIO, (char *)&tmp);
-
- nap_state = NAPS_ON;
- gui_stat((char *)MSG_STATUS2_LOGGINGINTO, nap_server);
- gui_state(1);
-
- DoMethod(gui->WI_Navigator, NAVI_MARKSERVER, nap_server);
-
- if (prf->regflag > 0) {
- r = nap_sendbuf(NAPC_CHECK_NAME, prf->user);
- /* Create user before we attempt to log in */
-
- if (r == -1) {
- prf->regflag = 1;
- if (Errno() == EPIPE) {
- gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_server, getneterror(Errno()));
- nap_logout();
- return;
- }
- }
- }
-
- if (prf->regflag == 1) {
- sprintf(nap_buf, "%s %s %d \"%s\" %d", prf->user, prf->pass, 0/*prf->port*/, prf->napvers, prf->link);
- }
- else {
- sprintf(nap_buf, "%s %s %d \"%s\" %d", gui->ConnectUser, gui->ConnectPw, 0/*prf->port*/, prf->napvers, prf->link);
- }
- prf->regflag = 1;
- nap_send(NAPC_LOGIN_REQUEST);
- }
- break;
-
- case NAPS_ON:
- while (1) {
- int r;
- FD_ZERO(&fds);
- FD_SET(nap_sock,&fds);
- tv.tv_sec=0;
- tv.tv_usec=0;
- if (WaitSelect(nap_sock+1, &fds, NULL, NULL, &tv, 0) < 1) {
- return;
- }
-
- r = nap_recv(buf);
- if (r == -1) {
- gui_stat((char *)MSG_ERR_NETWORKERROR);
- nap_logout();
- return;
- }
- if (r == 1) nap_interpret(buf[2]+(buf[3]<<8), buf+4);
- }
- }
- }
-
-
- void nap_send(u_int com)
- {
- int len;
-
- if (!gui_napon) return;
- /* Avoid crash - but calling functions should check this first! */
-
- len = strlen(nap_buf);
- nap_buffer[0] = len&0xFF;
- nap_buffer[1] = (len&0xFF00)>>8;
- nap_buffer[2] = com&0xFF;
- nap_buffer[3] = (com&0xFF00)>>8;
- send(nap_sock,nap_buffer,4+len,0);
- }
-
-
- int nap_sendbuf(u_int com, char *buf)
- {
- static u_char hdr[4];
- int len, r;
-
- if (!gui_napon) return -1;
- /* Avoid crash - but calling functions should check this first! */
-
- len = strlen(buf);
- hdr[0] = len&0xFF;
- hdr[1] = (len&0xFF00)>>8;
- hdr[2] = com&0xFF;
- hdr[3] = (com&0xFF00)>>8;
-
- r = send(nap_sock, hdr, 4, 0);
- if (r <= 0) return r;
-
- r = send(nap_sock, buf, len, 0);
- if (r <= 0) return r;
- else return 0;
- }
-
-
- void nap_songfree(song s)
- {
- if (!s) return;
- if (s->title) free(s->title);
- if (s->md5) free(s->md5);
- if (s->user) free(s->user);
- free(s);
- }
-
-
- song nap_songdup(song s)
- {
- song sn;
-
- sn = malloc(sizeof(_song));
- if (!sn) return(NULL);
- memset(sn,0,sizeof(_song));
-
- sn->title = strdup(s->title);
- sn->md5 = strdup(s->md5);
- sn->size = s->size;
- sn->bit = s->bit;
- sn->freq = s->freq;
- sn->time = s->time;
- sn->user = strdup(s->user);
- sn->ip = s->ip;
- sn->link = s->link;
-
- if (!sn->title || !sn->md5 || !sn->user) {
- nap_songfree(sn);
- return(NULL);
- }
-
- return(sn);
- }
-
-
- char *nap_strippath(char *name)
- {
- int i;
- char tmp;
-
- for (i=strlen(name)-1; i>=0; i--) {
- tmp = name[i];
- if (tmp==':' || tmp=='/' || tmp=='\\') return(name+i+1);
- }
- return(name);
- }
-
-
- /* private functions */
-
- int nap_connect(char *server)
- {
- struct hostent *host;
- struct sockaddr_in sin;
- long tmp=1;
- char *addr, *col;
- int port = 0;
-
- addr = strdup(server);
- col = strtok(addr, ":");
- if (col) col = strtok(NULL,"");
- if (col) port = atoi(col);
-
- if (!port) {
- gui_stat((char *)MSG_INFO_PORTNEEDED);
- free(addr);
- return(0);
- }
-
- host = gethostbyname(addr);
- free(addr);
- if (!host) {
- gui_stat((char *)MSG_ERR_LOOKUPFAILED);
- return(0);
- }
- memcpy(&sin.sin_addr, host->h_addr, host->h_length);
- sin.sin_family = host->h_addrtype;
- sin.sin_port = port;
- sin.sin_len = sizeof(sin);
-
- strcpy(nap_host, host->h_name);
- strcpy(nap_server, server);
-
- nap_sock = socket(AF_INET,SOCK_STREAM,0);
- if (nap_sock<0) {
- gui_debug((char *)MSG_ERR_SOCKETERROR);
- return(0);
- }
-
- IoctlSocket(nap_sock,FIOASYNC,(char *)&tmp);
- IoctlSocket(nap_sock,FIONBIO,(char *)&tmp);
-
- tmp = connect(nap_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
- if(tmp != -1) return(1);
- if(Errno()==EINPROGRESS) return(1);
-
- gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_host, getneterror(Errno()));
- return(0);
- }
-
-
- int nap_recv(u_char *buf)
- {
- static u_int blen=0;
- u_int len=4;
- int ret;
-
- if (blen>=4) {
- len = buf[0] + (buf[1]<<8) + 4;
- if (len==0) {
- buf[blen] = 0;
- blen = 0;
- return(1);
- }
- }
-
-
- ret = recv(nap_sock, buf+blen, len-blen, 0);
- if (ret <= 0) {
- blen = 0;
- return(-1);
- }
- blen += ret;
-
-
- if (blen == 4) {
- len = buf[0] + (buf[1]<<8) + 4;
- if (len == 0) {
- buf[blen] = 0;
- blen = 0;
- return(1);
- }
- }
-
- if (blen == len) {
- buf[blen] = 0;
- blen = 0;
- return(1);
- }
-
- return(0);
- }
-
-
- void nap_interpret(u_int com, char *data)
- {
- switch(com) {
- case NAPC_PUBLICMSGRECV:
- case NAPC_JOINACK:
- case NAPC_JOINMSG:
- case NAPC_USERPART:
- case NAPC_USERLIST:
- case NAPC_USERLISTEND:
- case NAPC_CHANNELTOPIC:
- chat_interpret(com, data);
- break;
- case NAPC_CHANNELPART:
- gui_debugf("Left channel %s.", data);
- break;
- case NAPC_CHANNEL_ENTRY:
- {
- char *channel;
- int users;
-
- channel = nap_token(&data);
- users = nap_itoken(&data);
- DoMethod(gui->WI_ChannelList, CHANLIST_ENTRY, channel, users, data);
- break;
- }
- case NAPC_LIST_CHANNELS:
- /* End of channel list */
- break;
- case NAPC_USER_SIGNON:
- case NAPC_USER_SIGNOFF:
- case NAPC_HOTLIST_ACK:
- case NAPC_HOTLIST_ERROR:
- HotlistInterpret(com, data);
- break;
- case NAPC_LOGINERROR:
- gui_debugf((char *)MSG_INFO_LOGINERROR, data);
- break;
- case NAPC_REGSUCCESS:
- gui_debug((char *)MSG_INFO_REGSUCCESS);
- break;
- case NAPC_REGUSED:
- gui_debug((char *)MSG_INFO_REGUSED);
- break;
- case NAPC_SEARCHRESULT:
- nap_parseresult(0, data);
- break;
- case NAPC_SEARCHCOMPLETE:
- gui_found(NULL, 0);
- break;
- case NAPC_BROWSERESULT:
- nap_parseresult(1, data);
- break;
- case NAPC_BROWSECOMPLETE:
- gui_found(NULL, 1);
- break;
- case NAPC_FILECOUNT:
- {
- int a,b,c;
- a = nap_itoken(&data);
- b = nap_itoken(&data);
- c = nap_itoken(&data);
- gui_srvstat(a,b,c);
- break;
- }
- case NAPC_PRIVATEMSG:
- {
- char *nick;
-
- nick = nap_token(&data);
- DoMethod(gui->mwin, MSG_GOT, nick, data);
- break;
- }
- case NAPC_FILEINFO:
- {
- char *title,*user;
- u_long ip;
- int port;
-
- user = nap_token(&data);
- ip = nap_ltoken(&data);
- port = nap_itoken(&data);
- title = nap_token(&data);
-
- DoMethod(gui->dwin, DL_START, title, user, NAP_SWAPIP(ip), port);
- }
- break;
- case NAPC_LOGINRESP:
- DoMethod(gui->WI_Hotlist, HOTLIST_UPLOAD);
- DoMethod(gui->shwin, SHARE_NOTIFYALL);
- gui_state(2);
- break;
- case NAPC_WHOISRESP:
- msg_gotwhois(data);
- break;
- case NAPC_WHOWASRESP:
- {
- char *user, *level;
- u_long lastseen;
-
- user = nap_token(&data);
- level = nap_token(&data);
- lastseen = nap_ltoken(&data);
-
- DoMethod(gui->mwin, MSG_WHOWAS, user, level, lastseen);
- }
- break;
- case NAPC_UPLOADREQ:
- {
- char *user,*fname;
- user = nap_token(&data);
- fname = nap_token(&data);
- upload_req(user,fname);
- }
- break;
- case NAPC_ALTDLACK:
- {
- char *nick, *fname, *md5;
- u_long ip;
- int port, speed;
-
- nick = nap_token(&data);
- ip = nap_ltoken(&data);
- port = nap_itoken(&data);
- fname = nap_token(&data);
- md5 = nap_token(&data);
- speed = nap_itoken(&data);
-
- ul_startq(fname, nick, NAP_SWAPIP(ip), port, speed);
- }
- break;
- case NAPC_REMOTEQUEUEFULL:
- {
- char *nick, *fname;
- int size, limit;
- nick = nap_token(&data);
- fname = nap_token(&data);
- size = nap_itoken(&data);
- limit = nap_itoken(&data);
-
- DoMethod(gui->dwin, DL_RETRY, fname, nick, limit);
- }
- break;
- case NAPC_GETERROR:
- case NAPC_GETERROR2:
- {
- char *user, *fname;
- user = nap_token(&data);
- fname = nap_token(&data);
- DoMethod(gui->dwin, DL_SETERROR, fname, user, ERROR_LOGGEDOUT);
- }
- break;
- case NAPC_GENERALERROR:
- gui_debugf((char *)MSG_INFO_ERROR, data);
- break;
- case NAPC_SYSMSG:
- gui_debug(data);
- break;
- case NAPC_GLOBALMSG:
- {
- char *nick, buf[50];
-
- nick = nap_token(&data);
- sprintf(buf, MSG_GLOBALMESSAGE_TITLE, nick);
-
- MUI_Request(gui->app, gui->win, 0L,
- buf,
- (char *)MSG_OK_GAD,
- data);
- }
- break;
- default:
- gui_debugf("<<%d:%s>>",com,data);
- }
- }
-
-
- void nap_parseresult(int type, char *data)
- {
- song s;
- char *tmp=data;
-
- s = malloc(sizeof(_song));
- if(!s) return;
- memset(s,0,sizeof(_song));
-
- switch (type) {
- case 0: /* Search result */
- s->title = strdup(nap_token(&tmp));
- s->md5 = strdup(nap_token(&tmp));
- strtok(s->md5,"-");
- s->size = nap_ltoken(&tmp);
- s->bit = nap_itoken(&tmp);
- s->freq = nap_itoken(&tmp);
- s->time = nap_itoken(&tmp);
- s->user = strdup(nap_token(&tmp));
- s->ip = nap_ltoken(&tmp);
- s->ip = NAP_SWAPIP(s->ip);
- s->link = nap_itoken(&tmp);
- break;
-
- case 1: /* Browse result */
- s->user = strdup(nap_token(&tmp));
- s->title = strdup(nap_token(&tmp));
- s->md5 = strdup(nap_token(&tmp));
- strtok(s->md5, "-");
- s->size = nap_ltoken(&tmp);
- s->bit = nap_itoken(&tmp);
- s->freq = nap_itoken(&tmp);
- s->time = nap_itoken(&tmp);
- break;
- }
-
- if (!s->user || !s->title || !s->md5) {
- nap_songfree(s);
- return;
- }
-
- gui_found(s, type);
- }
-
-
- u_long nap_ltoken(char **str)
- {
- char *t;
-
- t = nap_token(str);
- if(!t) return(0);
- return((u_long)atol(t));
- }
-
-
- int nap_itoken(char **str)
- {
- char *t;
-
- t = nap_token(str);
- if(!t) return(0);
- return(atoi(t));
- }
-
-
- char *nap_token(char **str)
- {
- int sf=0,i,len=0;
- char c, *t=NULL;
-
- if (!*str) return(NULL);
-
- for (i=0; ; i++) {
- c = *(*str + i);
- switch (c) {
- case '\0':
- *str = NULL;
- if (len==0 || sf) return(NULL);
- return(t);
- case '"':
- if (sf) {
- *(*str+i) = 0;
- *str = *str+i+1;
- return(t);
- }
- sf=1;
- break;
- case ' ':
- if (len==0) break;
- if (!sf) {
- *(*str+i) = 0;
- *str = *str+i+1;
- return(t);
- }
- break;
- default:
- if (!t) t=*str+i;
- len++;
- }
- }
- }
-
-
- /*
- int createlistener(void)
- {
- struct sockaddr_in server;
-
- if (loc_sock != -1) return 1;
-
- loc_sock = socket(AF_INET, SOCK_STREAM, 0);
- if (loc_sock < 0) {
- gui_debug("Error creating listener socket!\n");
- return 0;
- }
-
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = htonl(INADDR_ANY);
- server.sin_port = htons(prf->port);
-
- if (bind(loc_sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
- gui_debug("Error binding listening socket\n");
- CloseSocket(loc_sock);
- loc_sock = -1;
- return 0;
- }
-
- listen(loc_sock, 0); / Number of allowed connections /
-
- return 1;
- }
- */
-
-
- char *getneterror(int type)
- {
- char *message, buf[512];
-
- switch (type) {
- case ENETDOWN:
- message = (char *)MSG_NETERROR_ENETDOWN;
- break;
- case ENETUNREACH:
- message = (char *)MSG_NETERROR_ENETUNREACH;
- break;
- case ECONNRESET:
- message = (char *)MSG_NETERROR_ECONNRESET;
- break;
- case ETIMEDOUT:
- message = (char *)MSG_NETERROR_ETIMEDOUT;
- break;
- case ECONNREFUSED:
- message = (char *)MSG_NETERROR_ECONNREFUSED;
- break;
- case EPIPE:
- message = (char *)MSG_NETERROR_EPIPE;
- break;
- default:
- sprintf(buf, MSG_NETERROR_UNKNOWN, type);
- message = buf;
- }
-
- return message;
- }
-